//////////////////////////////////////////////////////////////////////////
//	DXRender Win32
//	Purpose:	Handles rendering for the application in DirectX
//	Created:	October 22, 2009
//////////////////////////////////////////////////////////////////////////
#ifndef C_DXRENDER_WIN32_H
#define C_DXRENDER_WIN32_H

//Include files for Windows STL objects
#include <vector>

// The include files for Direct3D9
#include <d3d9.h>
#include <d3dx9.h>

// The library files for Direct3D9
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment (lib, "dxguid.lib")


using std::vector;

//Forward Declarations
class IDXRenderable;
class CDXMeshManager;
class CDXTextureManager;
class CDXLights;
class CDXCamera;
class CDXRenderToTexture;



class CDXRenderWin32
{
private:
	CDXRenderToTexture* m_RenderToTexture;

	//Singleton Instance
	static CDXRenderWin32	m_instance;

	//HACK light
	D3DLIGHT9 light;

	// Camera
	CDXCamera* m_pCamera;

	//Trilogy of EVIL (special guest: constructor)
	//Class Constructor (DEACTIVATED)
	CDXRenderWin32();
	//Copy Constructor (DEACTIVATED)
	CDXRenderWin32(const CDXRenderWin32&);
	//Destructor (DEACTIVATED)
	~CDXRenderWin32();
	//Assignment Operator (DEACTIVATED)
	CDXRenderWin32& operator=(const CDXRenderWin32&);


	//////////////////////////////////////////////////////////////////////////
	//Device!!
	//////////////////////////////////////////////////////////////////////////
	IDirect3D9 *pD3d;
	IDirect3DDevice9 *pDXDevice;

	//////////////////////////////////////////////////////////////////////////
	//Current Shaders
	//////////////////////////////////////////////////////////////////////////
	LPDIRECT3DPIXELSHADER9	m_curPixelShader;
	LPDIRECT3DVERTEXSHADER9	m_curVertexShader;

	//////////////////////////////////////////////////////////////////////////
	//Engine Systems
	//////////////////////////////////////////////////////////////////////////
	CDXMeshManager*			m_pMeshManager;
	CDXTextureManager*		m_pTextureManager;

	bool m_bIsSceneRenderedToTexture;

	//////////////////////////////////////////////////////////////////////////
	//	DXCreateEffectFromFile - PRIVATE - Functions that may have a use..don't use yet.
	//	Purpose: Wraps the Function "D3DXCreateEffectFromFile"
	//	In:
	//	Out: HRESULT
	//////////////////////////////////////////////////////////////////////////
	HRESULT DXCreateEffectFromFile(	LPDIRECT3DDEVICE9 theDevice,
		LPCSTR srcFile,
		CONST D3DXMACRO* pDefines,
		LPD3DXINCLUDE pInclude,
		DWORD Flags,
		LPD3DXEFFECTPOOL pPool,
		LPD3DXEFFECT* ppEffect, 
		LPD3DXBUFFER* ppErros );

	//////////////////////////////////////////////////////////////////////////
	//	DXCreateTextureFromFile - PRIVATE - Functions that may have a use..don't use yet.
	//	Purpose: Wraps the Function "D3DXCreateTextureFromFileEx"
	//	In:
	//	Out: HRESULT
	//////////////////////////////////////////////////////////////////////////
	HRESULT DXCreateTextureFromFile(LPDIRECT3DDEVICE9 theDevice,
		LPCSTR srcFile,
		UINT uWidth,
		UINT uHeight,
		UINT uMipLvls,
		DWORD dUsage,
		D3DFORMAT dPormat,
		D3DPOOL dPool,
		DWORD dFilter,
		DWORD dMipFilter,
		D3DCOLOR dColorKey,
		D3DXIMAGE_INFO* pSrcInfo,
		PALETTEENTRY* pPalette,
		LPDIRECT3DTEXTURE9* ppTexture);

public:

	//////////////////////////////////////////////////////////////////////////
	//	Init
	//	Purpose:	Sets up renderer for rendering.
	//	In: HWND - The window we wish to do rendering on
	//		bool - Are we rendering the scene to a texture?
	//	Out:
	//	Return:	bool - true if successful.
	//////////////////////////////////////////////////////////////////////////
	bool Init(HWND, int, int,bool );

	//////////////////////////////////////////////////////////////////////////
	//	Shutdown
	//	Purpose:	Cleans up memory created by DXRender
	//////////////////////////////////////////////////////////////////////////
	void Shutdown();

	//////////////////////////////////////////////////////////////////////////
	//	Render
	//	Purpose:	Renders objects in the render list to the screen.
	//	In:	const vector<IDXRenderable*>* - The drawlist. This should be generated
	//										by either the state, or an object manager.
	//	Out:
	//////////////////////////////////////////////////////////////////////////
	void Render(const vector<IDXRenderable*>* drawlist);

	//////////////////////////////////////////////////////////////////////////
	// Clear
	// Purpose: Clears the back buffer to a specified color
	// In:	D3DCOLOR - Clear color 
	//////////////////////////////////////////////////////////////////////////
	void Clear(	D3DCOLOR clearColor, 
				float Z = 1.0f, 
				DWORD flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
				DWORD numRects = 0, 
				const D3DRECT* rectArray = NULL, 
				DWORD stencil = 0);


	

	//////////////////////////////////////////////////////////////////////////
	//	GetInstance
	//	Purpose:	Returns the singleton Instance of the renderer.
	//	Return:	CDXRenderWin32* - The singleton instance.
	//////////////////////////////////////////////////////////////////////////
	static CDXRenderWin32* GetInstance()	{	return &m_instance;	}
	

	//////////////////////////////////////////////////////////////////////////
	//	Name: TurnLightsOn
	//	Purpose: Turns on a light
	//	In: wIndex - what light to turn on
	//		bEnable - True to be on, False to be off.
	//	Out:
	//	Return:	HRESULT - Error code
	//////////////////////////////////////////////////////////////////////////
	HRESULT TurnLightsOn(WORD wIndex, BOOL bEnable)
	{
		return pDXDevice->LightEnable(wIndex, bEnable);
	}

	//////////////////////////////////////////////////////////////////////////
	//	Name: SetLights
	//	Purpose: Set a light
	//	In: wIndex - what light to set
	//		pLight - pointer to the light to set.
	//	Out:
	//	Return:	HRESULT - Error code
	//////////////////////////////////////////////////////////////////////////
	HRESULT SetLights(DWORD wIndex, CONST D3DLIGHT9 *pLight )
	{
		return pDXDevice->SetLight( wIndex, pLight );
	}
	

	//////////////////////////////////////////////////////////////////////////
	//----------------------Some RenderStates------------------------------
	//////////////////////////////////////////////////////////////////////////
	// 	*  D3DRS_STENCILENABLE - set this to TRUE to enable stenciling. Note that you must have created a stencil buffer when you created your device.
	// 	* D3DRS_STENCILFUNC - here you can define what comparison function to perform on the stencil value and the reference value (below).
	// 	* D3DRS_STENCILREF - a reference value you want to use in the comparison
	// 	* D3DRS_STENCILFAIL - if a stencil test fails this defines what operation to perform. There are many possible values.
	// 	* D3DRS_STENCILZFAIL - if the stencil test passes but the depth test fails this defines what operation will be performed.
	// 	* D3DRS_STENCILPASS - if both the stencil and depth test pass this defines what operation to perform.
	// 	* D3DRS_STENCILMASK - you can mask out bits when comparing the reference and stencil buffer values.
	// 	* D3DRS_STENCILWRITEMASK  - you can also mask out bits when writing to the stencil buffer.

	//////////////////////////////////////////////////////////////////////////
	//	Name: SetRenderState
	//	Purpose: You can use this to set render states, if a predefined one is not written.
	//	In: d3dRenderState - what stated you want.
	//		dwValue - value of the state.
	//	Out:
	//	Return:	HRESULT - Error code
	//////////////////////////////////////////////////////////////////////////
	HRESULT SetRenderState(D3DRENDERSTATETYPE d3dRenderState, DWORD dwValue );
	
	//////////////////////////////////////////////////////////////////////////
	//	Name: SetRenderStateDisableBlending
	//	Purpose: toggles Blending
	//	In: bIson - true to enable, false to disable.
	//	Out:
	//	Return:
	//////////////////////////////////////////////////////////////////////////
	void SetRenderStateBlending(bool bIson);

	//////////////////////////////////////////////////////////////////////////
	//	Name: SetRenderStateWireFrame
	//	Purpose: toggles WireFrame
	//	In: bIson - true to enable, false to disable.
	//	Out:
	//	Return:
	//////////////////////////////////////////////////////////////////////////
	void SetRenderStateWireFrame(bool bIsOn);
	
	//Accessors
	const LPDIRECT3DDEVICE9 GetDevice() const { return pDXDevice; } 
	const bool GetIsSceneRenderedToTexture() const { return m_bIsSceneRenderedToTexture; } 

	//Mutators
	void SetIsSceneRenderedToTexture(bool bIsSceneRenderedToTexture)  { m_bIsSceneRenderedToTexture = bIsSceneRenderedToTexture; } 


};
#endif